# -*- coding: UTF-8 -*-

"""
@author: 肥仔编程
@file:13.py
@time:2021-04-22
"""


"""
    理解面向对象
        1. 面向对象的理解
        2. 封装、继承、多态的理解
"""

"""
    类定义  class 类名(继承对象) ，object 表示顶级对象
    self，对象本身，可以代指任何创建的对象
    __init__， 类似构造方法，
    __str__，类似 toString() 方法，添加后可以输出处理后的字符串，不然输出对象时输出的是对象地址
    在类中可以定义方法，也可以定义变量
"""
# class Person(object):
#
#     def __init__(self, name, sex, age):
#         self.name = name
#         self.sex = sex
#         self.age = age
#
#     def sayHi(self):
#         print(f'大家好，我是{self.name}，{self.sex}生， 今年{self.age}岁了')


# class Teacher(Person):
#
#     def __init__(self, name, sex, age, work, record):
#         self.name = name
#         self.sex = sex
#         self.age = age
#         self.work = work
#         self.record = record
#
#     def sayHi(self):
#         print(f'大家好，我是{self.name}，{self.sex}生， 学历{self.record}，今年{self.age}岁了, 是一名{self.work}老师')
#
#     def __str__(self):
#         return f'大家好，我是{self.name}，{self.sex}生， 学历{self.record}，今年{self.age}岁了, 是一名{self.work}老师'


# wang = Teacher('张无忌', '男', 21, '语文', '本科')
#
# print(wang)

"""
    理解继承
        父类中包含的属性和方法，继承的子类自动拥有这些属性和方法
        单继承， class 类名(父类名)
        多继承， class 类名(父类名1， 父类名2) 注意，
                当继承多个类时，,如果方法铭相同，默认采用第一个类的属性和方法
                这里注意构造方法也会默认使用第一个
        子类中可以重新定义属性和方法，也就是说子类中可定义和父类中相同名称的属性和方法，这时候调用时默认使用子类自定义的属性和方法
        子类调用父类同名方法
            第一步，在子类中定义对应的方法
            第二步，在子类中使用父类名的方式分别调用初始化以及执行方法
        supper() 方法可以调用父类的方法，自动查找父类方法，但要注意，如果父类中没有定义 supper 无法向上查找
    类名.__mro__ 查看继承情况    
"""

# class Person(object):
#
#     def __init__(self, name, sex, age):
#         self.name = name
#         self.sex = sex
#         self.age = age
#
#     def sayHi(self):
#         print(f'大家好，我是{self.name}，{self.sex}生')
#
# class Teacher(object):
#
#     def __init__(self, name, sex, age, work):
#         self.name = name
#         self.sex = sex
#         self.age = age
#         self.work = work
#
#     def sayHi(self):
#         print(f'大家好，我是{self.name}，{self.sex}生，今年{self.age}岁了, 一名{self.work}老师')
#
#     def sayWork(self):
#         print("我是一名体育老师")
#
# class MathTeacher(Teacher, Person):
#
#     # 子类中调用父类的方法
#     def person_sayHi(self):
#         Person.__init__(self, name='宋远桥', sex='男', age=25)
#         Person.sayHi(self)
#
# wang = MathTeacher(name='宋远桥', sex='男', age=25, work='体育')
#
# wang.sayHi()
#
# wang.person_sayHi()
#
# print(MathTeacher.__mro__)

"""
    私有权限
        继承关系中，不想让继承类拥有的属性或方法，可以添加权限设置，进行限制
        实现，在属性名和方法名前边添加两个下划线
        设置的私有属性和方法，只可以在类中进行访问和修改
        Python 中可以通过定义 set_XXX 方法来设置私有属性的值，定义 get_XXX 方法获取私有属性的值
"""
# class Person(object):
#
#     def __init__(self, name, sex, age):
#         self.name = name
#         self.sex = sex
#         self.age = age
#
#     def sayHi(self):
#         print(f'大家好，我是{self.name}，{self.sex}生， 今年{self.age}岁了')
#     # 自定义属性和方法
#     def __mySecret(self):
#         print("这是的秘密")
#
# class Teacher(Person):
#     pass
#
# wang = Teacher('张无忌', '男', 21)


"""
    多态的理解
        实现
            1. 定义父类，声明公共方法
            2. 定义子类，重写父类方法
            3. 传递子类给调用者，观察看到传入的子类对象不同，执行情况也不同
"""

"""
    类属性
        定义在类中的变量，需要通过类名/对象名进行访问
        对于类属性修改，不能用对象，如果使用对象，只是为当前对象添加了一个属性，并不会影响到类中属性的值
"""

"""
    类方法
        实例方法，可以被类对象调用，但是不可以用类进行调用，定义时参数需要包含 self关键字
        类方法，可以被类或者实例对象调用，定义时需要用 cls ，而且还需要在函数前加 @classmethod，可以用来提供访问类私有属性
        静态方法，
            可以用实例对象调用，也可以用类调用，特点没有参数限制，定义时需要在函数前加 @staticmethod 修饰
            不需要使用类或者实例对象时，使用可以减少不必要的参数传递，降低内存占用和性能消耗     
    静态属性，在类的函数上加上 @property 可以将类设置为数据属性，这样在调用函数时，必须不带 () 执行
"""

class Person():

    __secret = '我有一百万'

    @classmethod
    def get_secret(cls):
        return cls.__secret

    @staticmethod
    def print_secret():
        print("打印一下我的秘密")

wang = Person()

print(wang.get_secret(), Person.get_secret())

print(wang.print_secret(), Person.print_secret())





